package com.example.jimuyutabletcontrol.activity;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.example.jimuyutabletcontrol.R;
import com.example.jimuyutabletcontrol.adapter.infoadapter.AuvInfomationAdapter;
import com.example.jimuyutabletcontrol.bean.AuvInfomation;
import com.example.jimuyutabletcontrol.bean.auv_infomation.AuvContent;
import com.example.jimuyutabletcontrol.bean.auv_infomation.AuvInfoAc;
import com.example.jimuyutabletcontrol.bean.auv_infomation.AuvTip;
import com.example.jimuyutabletcontrol.network.udp.UdpMessageHandle;
import com.example.jimuyutabletcontrol.network.udp.UdpMessageType;
import com.example.jimuyutabletcontrol.network.udp.UdpSocket;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;

public class AUVInformationActivity extends AppCompatActivity implements View.OnClickListener {
    private String auvcode;

    private UdpMessageHandle handle;

    private Point[] pentagonVertices;
    private FloatingActionButton fabTool;
    private Button[] buttonsTool;
    private int startPositionX;
    private int startPositionY;
    private int toolsWhichAnimation;
    private int[] enterDelay = {0, 40, 80, 120, 160, 200, 240};
    private int[] exitDelay = {0, 40, 80, 120, 160, 200, 240};
    private Boolean isFabToolsClicked = false;

    private RecyclerView mRecyclerView;

    private List<AuvInfoAc> infoAcs;

    private AuvInfomationAdapter mAdapter;

    private AuvInfomation auvInfo;

    private Timer timer;

    private TimerTask task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.auvinformationinterface_activity);
        auvcode = getIntent().getStringExtra("IMEI");
        initView();
        setAdapter();
        prepareFloatButton();
        setListeners();
        UdpSocket.getInstance().sendMessage("B" + auvcode + "AUV-information");
    }

    private void setAdapter() {
        infoAcs = new ArrayList<>();
        addPowerInfo(null);
        addSensorInfo(null);
        addVehicleInformation(null);
        addControlUnitInfo(null);
        mAdapter = new AuvInfomationAdapter(infoAcs);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void initView() {
        mRecyclerView = findViewById(R.id.mRecyclerView);
    }

    private void setListeners() {
        handle = new UdpMessageHandle(UdpMessageType.ANSWER, this::addAUVInformation);
        UdpSocket.getInstance().setMessageCallback(handle);
    }

    private void addAUVInformation(String message) {
        runOnUiThread(() -> {
            String[] strs = message.split("nswer#AUV,");
            String json = strs[1];
            auvInfo = new Gson().fromJson(json, AuvInfomation.class);
            infoAcs.clear();
            addPowerInfo(auvInfo);
            addSensorInfo(auvInfo);
            addVehicleInformation(auvInfo);
            addControlUnitInfo(auvInfo);
            mAdapter.notifyDataSetChanged();
        });
    }

    private void addControlUnitInfo(AuvInfomation auvInfo) {
        infoAcs.add(new AuvTip("控制单元信息"));
        infoAcs.add(new AuvContent("GPS经度值", null == auvInfo ? "" : auvInfo.longitude));
        infoAcs.add(new AuvContent("GPS纬度值", null == auvInfo ? "" : auvInfo.latitude));
        infoAcs.add(new AuvContent("GPS精度值", null == auvInfo ? "" : auvInfo.accuracy));
        infoAcs.add(new AuvContent("GPS速度值", null == auvInfo ? "" : auvInfo.speed));
        infoAcs.add(new AuvContent("GPS时间", null == auvInfo ? "" : auvInfo.time));
        infoAcs.add(new AuvContent("航向角(度)", null == auvInfo ? "" : auvInfo.courseAngle));
        infoAcs.add(new AuvContent("俯仰角(度)", null == auvInfo ? "" : auvInfo.angleOfPitch));
        infoAcs.add(new AuvContent("横滚角(度)", null == auvInfo ? "" : auvInfo.rollAngle));
        infoAcs.add(new AuvContent("深度(米)", null == auvInfo ? "" : auvInfo.depth));
    }

    private void addVehicleInformation(AuvInfomation auvInfo) {
        infoAcs.add(new AuvTip("航行器信息"));
        infoAcs.add(new AuvContent("航信器型号", null == auvInfo ? "" : "TH-660"));
        infoAcs.add(new AuvContent("推进器型号", null == auvInfo ? "" : "RCD-MI60S"));
        infoAcs.add(new AuvContent("电源型号", null == auvInfo ? "" : "锂电池 22.2V 35AH"));
        infoAcs.add(new AuvContent("深度传感器型号", null == auvInfo ? "" : "MPM4730"));
        infoAcs.add(new AuvContent("舵机型号", null == auvInfo ? "" : "POWER HD L-15HV"));
    }

    private void addSensorInfo(AuvInfomation auvInfo) {
        infoAcs.add(new AuvTip("传感器信息"));
        infoAcs.add(new AuvContent("动力电量", null == auvInfo ? "" : auvInfo.auvBattery));
        infoAcs.add(new AuvContent("控制单元电量", null == auvInfo ? "" : auvInfo.phoneBattery));
    }

    private void addPowerInfo(AuvInfomation auvInfo) {
        infoAcs.add(new AuvTip("通讯状态检测"));
        infoAcs.add(new AuvContent("动力模块", null == auvInfo ? "" : auvInfo.selfPropeller));
        infoAcs.add(new AuvContent("深度模块", null == auvInfo ? "" : auvInfo.selfDepth));
        infoAcs.add(new AuvContent("动力模块", null == auvInfo ? "" : auvInfo.selfBattery));
    }

    @Override
    public void onClick(View view) {
        boolean isToolsSubClicked = false;
        switch (view.getId()) {
            case R.id.fab:
                isToolsSubClicked = true;
                isFabToolsClicked = true;
                if (toolsWhichAnimation == 0) {
                    /**
                     * Getting the center point of floating action button
                     *  to set start point of buttons
                     */
                    startPositionX = 2600;
                    startPositionY = 0;

                    for (Button button : buttonsTool) {
                        button.setX(startPositionX);
                        button.setY(startPositionY);
                        button.setVisibility(View.VISIBLE);
                    }
                    for (int i = 0; i < buttonsTool.length; i++) {
                        playEnterAnimation(buttonsTool[i], i);
                    }
                    toolsWhichAnimation = 1;
                } else {
                    for (int i = 0; i < buttonsTool.length; i++) {
                        playExitAnimation(buttonsTool[i], i);
                    }
                    toolsWhichAnimation = 0;
                    isFabToolsClicked = false;
                }
                break;
        }
        if (isFabToolsClicked && !isToolsSubClicked) {
            switch ((int) view.getTag()) {
                case 0:
                    if (null == auvInfo || auvInfo.selfPropeller.equals("异常")) {
                        toastMsg("推进器通信异常！请保证通信正常后再进行自检");
                    } else {
                        sendOrder();
                    }
                    break;

            }
        }
    }

    private void sendOrder() {
        UdpSocket.getInstance().sendMessage("B" + auvcode + "Self-Test");
        if (null != buttonsTool && buttonsTool.length > 0) {
            buttonsTool[0].setBackgroundResource(R.drawable.circular_gray_background);
            buttonsTool[0].setEnabled(false);
            buttonsTool[0].setClickable(false);
            buttonsTool[0].setText("自检中");
        }
        if (null != timer) {
            timer.cancel();
            timer = null;
        }
        if (null != task) {
            task.cancel();
            task = null;
        }
        timer = new Timer();
        task = new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(() -> {
                    buttonsTool[0].setBackgroundResource(R.drawable.circular_background);
                    buttonsTool[0].setEnabled(true);
                    buttonsTool[0].setClickable(true);
                    buttonsTool[0].setText("启动自检");
                });
            }
        };
        timer.schedule(task, 17 * 1000);
    }

    private void toastMsg(final String msg) {
        runOnUiThread(() -> Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show());
    }

    private void prepareFloatButton() {
        startPositionX = 0;
        startPositionY = 0;

        fabTool = findViewById(R.id.fab);
        fabTool.setOnClickListener(this);

        pentagonVertices = new Point[10];
        pentagonVertices[0] = new Point(2360, 200);
        pentagonVertices[1] = new Point(10, 280);
        pentagonVertices[2] = new Point(10, 460);
        pentagonVertices[3] = new Point(10, 640);
        pentagonVertices[4] = new Point(10, 820);
        pentagonVertices[5] = new Point(10, 1000);
        pentagonVertices[6] = new Point(10, 1180);

        String[] contentTools = {"启动自检"};

        buttonsTool = calculatePentagonVertices(contentTools.length, contentTools);
    }

    private Button[] calculatePentagonVertices(int number, String[] content) {

        Button[] buttons = new Button[number];

        for (int i = 0; i < buttons.length; i++) {
            //Adding button at (0,0) coordinates and setting their visibility to zero
            buttons[i] = new Button(AUVInformationActivity.this);
            buttons[i].setLayoutParams(new RelativeLayout.LayoutParams(100, 100));
            buttons[i].setX(0);
            buttons[i].setY(0);
            buttons[i].setTag(i);
            buttons[i].setOnClickListener(this);
            buttons[i].setVisibility(View.INVISIBLE);
            buttons[i].setBackgroundResource(R.drawable.circular_background);
            buttons[i].setTextColor(Color.DKGRAY);
            buttons[i].setText(content[i]);
            buttons[i].setTextSize(14);
            /**
             * Adding those buttons in acitvities layout
             */
            ((LinearLayout) findViewById(R.id.information_main)).addView(buttons[i]);
        }
        return buttons;

    }

    private void playEnterAnimation(final Button button, int position) {

        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(startPositionX,
                pentagonVertices[position].x);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(startPositionY,
                pentagonVertices[position].y);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will increase the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(6, 170);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(enterDelay[position]);
        buttonAnimator.start();
    }

    private void playExitAnimation(final Button button, int position) {

        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(pentagonVertices[position].x,
                startPositionX);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(pentagonVertices[position].y,
                startPositionY);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will decrease the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(170, 6);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(exitDelay[position]);
        buttonAnimator.start();
    }

    protected void onDestroy() {
        super.onDestroy();
        if (null != handle) {
            UdpSocket.getInstance().removeMessageCallback(handle);
            handle = null;
        }
        if (null != timer) {
            timer.cancel();
            timer = null;
        }
        if (null != task) {
            task.cancel();
            task = null;
        }
    }
}
